package cn.enilu.flash.api.controller.es;

import cn.enilu.flash.api.controller.BaseController;
import cn.enilu.flash.bean.vo.es.PageVo;
import com.alibaba.fastjson.JSONObject;
import com.mysql.cj.xdevapi.JsonArray;
import org.apache.lucene.queryparser.flexible.core.builders.QueryBuilder;
import org.apache.lucene.search.TotalHits;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.GeoDistanceQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

//import cn.enilu.flash.bean.entity.es.TestBean;
//import cn.enilu.flash.service.es.TestService;

@RestController
@RequestMapping("/test")
public class ESControllerController extends BaseController {
    @Autowired
    public RestHighLevelClient client;

    @RequestMapping("createIndex")
    public void findAll() throws IOException {
        CreateIndexRequest request =  new CreateIndexRequest("product");
        // 设置Request参数
        request.settings(Settings.builder()
                .put("index.number_of_shards", 3) // 设置分区数
                .put("index.number_of_replicas", 2) // 设置副本数
        );
        JSONObject mapping =  new JSONObject();

        JSONObject properties =  new JSONObject();

        //id
        JSONObject id =  new JSONObject();
        id.put("type", "keyword");
        properties.put("id", id);

        //名称
        JSONObject name =  new JSONObject();
        name.put("type", "text");
        properties.put("name", name);

        //价格
        JSONObject price =  new JSONObject();
        price.put("type", "double");
        properties.put("price", price);

        //产品描述
        JSONObject productdesc =  new JSONObject();
        productdesc.put("type", "text");
        properties.put("productdesc", productdesc);

        //地址详情
        JSONObject addressDetail =  new JSONObject();
        addressDetail.put("type", "keyword");
        properties.put("addressDetail", addressDetail);

        //地址
        JSONObject location =  new JSONObject();/**/
        location.put("type", "geo_point");
        properties.put("location", location);

        mapping.put("properties",properties);
        request.mapping(mapping.toJSONString(), XContentType.JSON);

        // 执行请求，创建索引
        CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);

        if (createIndexResponse.isAcknowledged()) {
            // 创建成功
            System.out.println("创建索引成功");

        }
    }
    /**
     * 添加数据
     */

    @RequestMapping("save")
    public void save() throws IOException {
        IndexRequest request =  new IndexRequest("product");
        request.id("1");
        JSONObject obj =  new JSONObject(){{
          put("name","张三");
          put("productdesc","零食加工");
          put("price",90);
          put("location",new double[]{116.365175,39.943264});
        }};
        request.source(obj.toJSONString(), XContentType.JSON);

        IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);

    }

    /**
     * 分页查询
     */
    @RequestMapping("page")
    public PageVo page(@RequestBody PageVo page) throws IOException {
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("product");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //searchSourceBuilder.query(QueryBuilders.matchAllQuery());
//        searchSourceBuilder.query(QueryBuilders.matchQuery("name","123"));
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
//        boolQueryBuilder.must(QueryBuilders.matchQuery("name","张三"));
        searchSourceBuilder.query(boolQueryBuilder);
        searchSourceBuilder.from((page.getPageNum()-1)*page.getPageSize());
        searchSourceBuilder.size(page.getPageSize());
        searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));

        //排序
        searchSourceBuilder.sort(new FieldSortBuilder("id").order(SortOrder.DESC));

        //返回字段
        searchSourceBuilder.fetchSource(new String[]{"name","price","productdesc","location"},new String[]{"addressDetail"});

         //按照距离搜索
        // 根据location坐标字段和当前位置，搜索1千米范围的数据
        GeoDistanceQueryBuilder geoQueryBuilder = QueryBuilders.geoDistanceQuery("location")
                .distance("1km") //设置搜索距离为1千米
                // 设置当前位置
                .point(new GeoPoint(39.943262, 116.365123));

        boolQueryBuilder.filter(geoQueryBuilder);

//        searchSourceBuilder.query(geoQueryBuilder);

        //1.按照地理位置设置排序
        // 构建GeoDistanceSortBuilder设置按距离排序参数
        GeoDistanceSortBuilder geoDistanceSortBuilder = SortBuilders.geoDistanceSort("location", new GeoPoint(39.943262, 116.365123));
        // 升序排序
        geoDistanceSortBuilder.order(SortOrder.ASC);
        // 设置排序参数
        searchSourceBuilder.sort(geoDistanceSortBuilder);


       //2.按照加个进行排序
//        searchSourceBuilder.sort("price",SortOrder.ASC);

        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

        RestStatus status = searchResponse.status(); // ES请求状态
       // 获取hits，SearchHits对象包含搜索结果
        SearchHits hits = searchResponse.getHits();

       // 搜索结果总数
        TotalHits totalHits = hits.getTotalHits();
        long numHits = totalHits.value;

        // 遍历搜索结果
        SearchHit[] searchHits = hits.getHits();

        Map<String,Object>  res = new HashMap<String,Object>();
        List<Map<String, Object>> data = new ArrayList<Map<String, Object>>();
//        res.put("data",data);
//        res.put("total",numHits);
        page.setTotal(Long.valueOf(numHits).intValue());
        page.setData(data);

        for (SearchHit hit : searchHits) {
            // 获取文档内容，json字符串格式
            String sourceAsString = hit.getSourceAsString();
            // 获取文档内容，Map对象格式
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            data.add(sourceAsMap);
        }
        return page;
    }


}
